package com.eastmountain.chinese.fullscreen;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

import com.eastmountain.chinese.common.FlashCardLessonSet;
import com.eastmountain.chinese.db.flashcards.records.ChineseElementProperties;
import com.eastmountain.chinese.fonts.ChineseFontChooser;
import com.eastmountain.chinese.gui.MainPanel;
import com.eastmountain.chinese.observable.HZFlashcardsDataModel;
import com.eastmountain.util.Helpers;
import com.eastmountain.util.PrintFile;

public class FramedSlideShow extends JFrame implements KeyListener {

    private HZFlashcardsDataModel hzFlashcardsDataModel = null;
    
    private PrintFile printFile = new PrintFile( "fontstuff.txt" );
    
    private GraphicsEnvironment graphicsEnvironment;
    private GraphicsDevice graphicsDevice;

    private DisplayMode originalDisplayMode;

    private JPanel displayPanel;

    private boolean isFullScreen = false;

    private static final int FONT_SIZE = 240;

    private static Font hanZiFont = new Font( "Dialog", Font.BOLD,
            FONT_SIZE );
    private static Font activeHanZiFont = hanZiFont;

    public static final int INDEX_WIDTH = 0;
    public static final int INDEX_HEIGHT = 1;
    public static final int INDEX_BITDEPTH = 2;
    public static final int INDEX_REFRESHRATE = 3;

    public static final String[] COLUMN_NAMES = new String[] { "Width",
            "Height", "Bit Depth", "Refresh Rate" };

    static final String newline = "\n";

    private static String japaneseString = "\u65e5\u672c\u8a9e\u6587\u5b57\u5217";

    public FramedSlideShow( Font font ) {

        String fontName;
        int fontStyle;

        // super(device.getDefaultConfiguration());
        
        this.activeHanZiFont = font;
        
        addWindowListener( new FramedSlideShowWindowAdapter( this ) );
        
        addKeyListener( this );
        
        //hzFlashcardsDataModel = HZFlashcardsDataModel.getInstance();
        //hzFlashcardsDataModel.addObserver( this );

        // the active font size is set for
        // HanZiDrawingSurface, so we make
        // it bigger for the full-screen
        // slide show.

        //Font biggerFont = activeHanZiFont.deriveFont( 240 );
        //activeHanZiFont = biggerFont;
         
        System.out.println( "*** Font chosen in FramedSlideShow:\n"
                            + activeHanZiFont.toString()  );
               
        printFile.println();
        printFile.println( "font Name",
                           activeHanZiFont.getName() );
        printFile.println( "font Style",
                activeHanZiFont.getStyle() );
        printFile.println( "font Size",
                activeHanZiFont.getSize() );


        setTitle( "Display Mode Test" );

        graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
        graphicsDevice = graphicsEnvironment.getDefaultScreenDevice();

        // get the first screen device

        GraphicsDevice[] graphicsDevices = graphicsEnvironment
                .getScreenDevices();
        originalDisplayMode = graphicsDevices[0].getDisplayMode();
        printDisplayModeValues( originalDisplayMode );

    }

    public void begin( FlashCardLessonSet flashCardLessonSet ) {

        ChineseElementProperties chineseElementProperties;

        initComponents();

        isFullScreen = graphicsDevice.isFullScreenSupported();

        setUndecorated( isFullScreen );
        setResizable( !isFullScreen );

        if ( isFullScreen ) {

            // Full-screen mode
            graphicsDevice.setFullScreenWindow( this );
            //validate();

        } else {

            // Windowed mode
            pack();
            setVisible( true );

        }

        try {

            while ( ( chineseElementProperties = (ChineseElementProperties)flashCardLessonSet
                    .nextFlashCard() ) != null ) {

                drawChineseElement( chineseElementProperties
                        .getChineseElement() );

                try {
                    Thread.sleep( 2000 );
                } catch ( InterruptedException e ) {
                }

            }

        } catch ( Exception exception ) {
            exception.printStackTrace();
        } finally {
            graphicsDevice.setFullScreenWindow( null );
        }

    }

    private void initComponents() {

        Component glassPane = getGlassPane();

        glassPane.addKeyListener( this );

        setBackground( Color.BLACK );

        displayPanel = new JPanel( new FlowLayout( FlowLayout.CENTER ) );
        displayPanel.addKeyListener( this );
        displayPanel.setPreferredSize( new Dimension( 400, 400 ) );
        displayPanel.setBackground( Color.BLACK );
        displayPanel.setOpaque( true );
        displayPanel.setFocusable( true );
        displayPanel.requestFocusInWindow();

        setContentPane( displayPanel );

    }

    private void drawChineseElement( String chineseElement ) {

        Graphics2D g2D = (Graphics2D) displayPanel.getGraphics();
        FontMetrics metrics;
        
        // Graphics2D g2D = (Graphics2D) g;

        int w = displayPanel.getWidth();
        int h = displayPanel.getHeight();

        g2D.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON );

        g2D.setPaint( Color.BLACK );
        g2D.fill( new Rectangle2D.Double( 0, 0, w, h ) );

        //g2D.setFont( activeHanZiFont );
        //FontMetrics metrics = g2D.getFontMetrics( activeHanZiFont );

        g2D.setColor( Color.BLACK );

        GradientPaint redtowhite = new GradientPaint( 0, 0, Color.RED, w, h,
                Color.WHITE );
        g2D.setPaint( redtowhite );
        Ellipse2D ellipse = new Ellipse2D.Double( 0, 0, w, h );
        g2D.fill( ellipse );

        g2D.setColor( Color.BLACK );

        g2D.setFont( activeHanZiFont );
        
        metrics = g2D.getFontMetrics();
        int textWidth = metrics.stringWidth( chineseElement );

        Point point = Helpers.calculateFieldPosition( g2D, chineseElement, w,
                h, activeHanZiFont );
        g2D.drawString( chineseElement, point.x, point.y );

        // int translateWidth = (int) (w * (1 - scaleX)) / 2;

        // g2D.translate( translateWidth, 0 );
        // g2D.scale( scaleX, 1.0 );

    }

    @Override
    public void setVisible( boolean isVis ) {
        super.setVisible( isVis );
    }
/*
    @Override
    public void update( Observable arg0, Object arg ) {

        System.out.println( "Class name: " + arg.getClass().getSimpleName() );

        if ( "Font".equals( arg.getClass().getSimpleName() ) ) {

            // activeHanZiFont = (Font) arg;

        }

        // repaint();

        // TODO Auto-generated method stub

    }
*/
    private void printDisplayModeValues( DisplayMode displayMode ) {

        int bitDepth = displayMode.getBitDepth();
        int refreshRate = displayMode.getRefreshRate();
        String bd, rr;
        if ( bitDepth == DisplayMode.BIT_DEPTH_MULTI ) {
            bd = "Multi";
        } else {
            bd = Integer.toString( bitDepth );
        }
        if ( refreshRate == DisplayMode.REFRESH_RATE_UNKNOWN ) {
            rr = "Unknown";
        } else {
            rr = Integer.toString( refreshRate );
        }
        System.out.println( COLUMN_NAMES[INDEX_WIDTH] + ": "
                + displayMode.getWidth() + " " + COLUMN_NAMES[INDEX_HEIGHT]
                + ": " + displayMode.getHeight() + " "
                + COLUMN_NAMES[INDEX_BITDEPTH] + ": " + bd + " "
                + COLUMN_NAMES[INDEX_REFRESHRATE] + ": " + rr );

    }

    /*
     * We have to jump through some hoops to avoid trying to print non-printing
     * characters such as Shift. (Not only do they not print, but if you put
     * them in a String, the characters afterward won't show up in the text
     * area.)
     */

    protected void displayInfo( KeyEvent e, String s, boolean skip ) {

        String displayArea = "";

        String keyString, modString, tmpString, actionString, locationString;

        // You should only rely on the key char if the event
        // is a key typed event.
        int id = e.getID();
        if ( id == KeyEvent.KEY_TYPED ) {
            char c = e.getKeyChar();
            keyString = "key character = '" + c + "'";
        } else {
            int keyCode = e.getKeyCode();
            keyString = "key code = " + keyCode + " ("
                    + KeyEvent.getKeyText( keyCode ) + ")";
        }

        int modifiers = e.getModifiersEx();
        modString = "modifiers = " + modifiers;
        tmpString = InputEvent.getModifiersExText( modifiers );
        if ( tmpString.length() > 0 ) {
            modString += " (" + tmpString + ")";
        } else {
            modString += " (no modifiers)";
        }

        actionString = "action key? ";
        if ( e.isActionKey() ) {
            actionString += "YES";
        } else {
            actionString += "NO";
        }

        locationString = "key location: ";
        int location = e.getKeyLocation();
        if ( location == KeyEvent.KEY_LOCATION_STANDARD ) {
            locationString += "standard";
        } else if ( location == KeyEvent.KEY_LOCATION_LEFT ) {
            locationString += "left";
        } else if ( location == KeyEvent.KEY_LOCATION_RIGHT ) {
            locationString += "right";
        } else if ( location == KeyEvent.KEY_LOCATION_NUMPAD ) {
            locationString += "numpad";
        } else { // (location == KeyEvent.KEY_LOCATION_UNKNOWN)
            locationString += "unknown";
        }

        if ( skip ) {
            displayArea = newline;
        }

        displayArea = displayArea + s + newline + "    " + keyString + newline
                + "    " + modString + newline + "    " + actionString
                + newline + "    " + locationString + newline;

        System.out.println( displayArea );

    }
/*
    @Override
    public void keyPressed( KeyEvent keyEvent ) {

        displayInfo( keyEvent, "KEY PRESSED", true );

        graphicsDevice.setDisplayMode( originalDisplayMode );
        System.exit( 0 );

    }

    @Override
    public void keyReleased( KeyEvent arg0 ) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyTyped( KeyEvent arg0 ) {
        // TODO Auto-generated method stub

    }
*/
    public static void main( String[] args ) {
        // GraphicsEnvironment env = GraphicsEnvironment.
        // getLocalGraphicsEnvironment();
        // GraphicsDevice[] devices = env.getScreenDevices();
        // REMIND : Multi-monitor full-screen mode not yet supported
        for ( int i = 0; i < 1 /* devices.length */; i++ ) {
            FramedSlideShow test = new FramedSlideShow( hanZiFont );
            // test.initComponents();
            test.begin( null );
        }
    }

    public void keyPressed( KeyEvent keyEvent ) {

        displayInfo( keyEvent, "KEY PRESSED", true );

        graphicsDevice.setDisplayMode( originalDisplayMode );
        //System.exit( 0 );
       
    }

    public void keyReleased( KeyEvent arg0 ) {
        // TODO Auto-generated method stub
        
    }

    public void keyTyped( KeyEvent arg0 ) {
        // TODO Auto-generated method stub
        
    }
}

/***************************************************************************************************
 *
 * CLASS FramedSlideShowWindowAdapter
 *
 **************************************************************************************************/

class FramedSlideShowWindowAdapter extends WindowAdapter {

    private JFrame frame;
    private MainPanel mainPanel;

    public FramedSlideShowWindowAdapter( JFrame frame ) {

        this.frame = frame;
        this.mainPanel = mainPanel;

    }

    @Override
    public void windowClosing( WindowEvent e ) {

        displayMessage( "WindowListener method called: windowClosing." );

        // JOptionPane.showMessageDialog( frame, "Window closing invoked."
        // );

        // A pause so user can see the message before
        // the window actually closes.

        ActionListener task = new ActionListener() {

            boolean alreadyDisposed = false;

            public void actionPerformed( ActionEvent e ) {

                if ( !alreadyDisposed ) {

                    alreadyDisposed = true;

                    frame.dispose();

                } else { // make
                    // sure
                    // the
                    // program
                    // exits

                    System.exit( 0 );

                }

            }

        };

        Timer timer = new Timer( 500, task ); // fire
        // every
        // half
        // second
        timer.setInitialDelay( 2000 ); // first
        // delay
        // 2
        // seconds
        timer.start();

    }

    @Override
    public void windowClosed( WindowEvent e ) {

        displayMessage( "WindowListener method called: windowClosed." );

    }

    void displayMessage( String msg ) {

        System.out.println( msg + "\n" );

    }

}
